probe healthcheck {
    .url = "/test.html";
    .interval = 5s;
    .timeout = 1s;
    .window = 5;
    .threshold = 3;
    .initial = 3;
}

backend node01 {
    .host = "192.168.1.242";
    .port = "8080";
    .probe = healthcheck;
}

backend node02 {
    .host = "192.168.1.243";
    .port = "8080";
    .probe = healthcheck;
}

backend image {
    .host = "betaftp.food86.org.cn";
    .port = "80";
}

director cluster round-robin {
    { .backend = node01; }
    { .backend = node02; }
}

sub get_lb_worker {
    if (req.http.Cookie ~ "JSESSIONID=") {
	set req.http.X-JSESSIONID = regsub(req.http.Cookie, "^.*?JSESSIONID=([^;]*);*.*$", "\1");
	set req.http.X-JSESSIONID-NODE = regsub(req.http.X-JSESSIONID, "^.+\.(.+)$", "\1");
    }

    unset req.http.X-JSESSIONID;
}

sub set_lb_worker {
    if (req.http.X-JSESSIONID-NODE ~ "^node01$") {
	set req.backend = node01;
    } elsif (req.http.X-JSESSIONID-NODE ~ "^node02") {
	set req.backend = node02;
    } else {
	set req.backend = cluster;
    }

    if (!req.backend.healthy && req.backend != cluster) {
	if (req.http.X-JSESSIONID-NODE ~ "^node01$") {
	    set req.backend = node02;
	} elsif (req.http.X-JSESSIONID-NODE ~ "^node02$") {
	    set req.backend = node01;
	}
    }

    unset req.http.X-JSESSIONID-NODE;
}

acl purge {
    "localhost";
    "127.0.0.1";
    "192.168.1.0"/24;
}

sub vcl_recv {
    if (req.url ~ "^/upload/") {
	unset req.http.cookie;
	set req.backend = image;
    } else {
	call get_lb_worker;
	call set_lb_worker;
    }

    if (req.request == "PURGE") {
	if (!client.ip ~ purge) {
	    error 405 "Not allowed.";
	}
    }

    if (req.http.Accept-Encoding) {
	if (req.http.Accept-Encoding ~ "gzip") {
	    set req.http.Accept-Encoding = "gzip";
	} elsif (req.http.Accept-Encoding ~ "deflate") {
	    set req.http.Accept-Encoding = "deflate";
	} else {
	    remove req.http.Accept-Encoding;
	}
    }

    if (req.restarts == 0) {
	if (req.http.x-forwarded-for) {
	    set req.http.X-Forwarded-For =
		req.http.X-Forwarded-For + ", " + client.ip;
	} else {
	    set req.http.X-Forwarded-For = client.ip;
	}
    }

    if (req.request != "GET" &&
      req.request != "HEAD" &&
      req.request != "PUT" &&
      req.request != "POST" &&
      req.request != "TRACE" &&
      req.request != "OPTIONS" &&
      req.request != "DELETE") {
        return (pipe);
    }

    if (req.request != "GET" && req.request != "HEAD") {
        return (pass);
    }

    if (req.http.Authorization || req.http.Cookie) {
        return (pass);
    }

    return (lookup);
}

sub vcl_pipe {
    return (pipe);
}
 
sub vcl_pass {
    return (pass);
}
 
sub vcl_hash {
    hash_data(req.url);
    if (req.http.host) {
        hash_data(req.http.host);
    } else {
        hash_data(server.ip);
    }
    return (hash);
}
 
sub vcl_hit {
    if (req.request == "PURGE") {
	set obj.ttl=0s;
	error 200 "Purged.";
    }
}
 
sub vcl_miss {
    if (req.request == "PURGE") {
	error 404 "Not in cache.";
    }

    return (fetch);
}
 
sub vcl_fetch {
    if (beresp.ttl <= 0s ||
        beresp.http.Set-Cookie) {
		set beresp.ttl = 120 s;
		return (hit_for_pass);
    }

    if (req.request == "GET" && req.url ~"^/upload/") {
	set beresp.ttl = 30d;
    }

    if (req.request == "GET" && req.url ~ "\.(css|js|jpg|jpeg|gif|png|xml|mp3|swf|ico|txt)$") {
	set beresp.ttl = 30d;
    }

    if (req.request == "GET" && req.url ~ "\.(html|htm)$") {
	set beresp.ttl = 3600s;
    }

    return (deliver);
}

sub vcl_deliver {
    return (deliver);
}

sub vcl_error {
    set obj.http.Content-Type = "text/html; charset=utf-8";
    set obj.http.Retry-After = "5";
    synthetic {"
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
  <head>
    <title>"} + obj.status + " " + obj.response + {"</title>
  </head>
  <body>
    <h1>Error "} + obj.status + " " + obj.response + {"</h1>
    <p>"} + obj.response + {"</p>
    <h3>Guru Meditation:</h3>
    <p>XID: "} + req.xid + {"</p>
    <hr>
    <p>Varnish cache server</p>
  </body>
</html>
"};
    return (deliver);
}
 
sub vcl_init {
	return (ok);
}
 
sub vcl_fini {
	return (ok);
}
